/**
 * 表示一本基本的书，包含基本的详细信息。
 */
class BasicBook {
    /**
     *
     * @param {String} name 书的名称。必填。
     * @param {String|null} author 书的作者。默认值为 "未知"。
     * @param {String} path 书的路径。必填。
     * @param {String|null} catalogPath 目录路径。有的书籍目录和详情的路径是分开的，在调用书籍目录方法时 path = catalogPath ?? path
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({name, author = BasicBook.unknownAuthor, path, catalogPath} = {}) {
        if (typeof name !== 'string') throw new Error('BasicBook: The "name" field must be a string and is required.');
        if (author && typeof author !== 'string') throw new Error('BasicBook: The "author" field must be a string.');
        if (typeof path !== 'string') throw new Error('BasicBook: The "path" field must be a string and is required.');
        if (catalogPath && typeof catalogPath !== 'string') throw new Error('BasicBook: The "catalogPath" field must be a string.');

        this.name = name;
        this.author = author;
        this.path = path;
        if (catalogPath) {
            this.catalogPath = catalogPath;
        }
    }

    static get unknownAuthor() {
        return "未知";
    }
}


/**
 * 表示一本书，包含更多详细信息。
 */
class Book extends BasicBook {
    /**
     *
     * @param {String} name 书的名称。必填。
     * @param {String} author 书的作者。默认值为 "未知"。
     * @param {String} path 书的路径。必填。
     * @param {String|null} catalogPath 目录路径。有的书籍目录和详情的路径是分开的，在调用书籍目录方法时 path = catalogPath ?? path
     * @param {String} intro 书的简介。
     * @param {String} coverUrl 书的封面URL。
     * @param {String} type 书的类型。
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({
                    name, author = BasicBook.unknownAuthor, path, catalogPath, intro, coverUrl, type
                } = {}) {
        super({name, author, path, catalogPath});

        if (intro && typeof intro !== 'string') throw new Error('Book: The "intro" field must be a string.');
        if (coverUrl && typeof coverUrl !== 'string') throw new Error('Book: The "coverUrl" field must be a string.');
        if (type && typeof type !== 'string') throw new Error('Book: The "type" field must be a string.');

        this.intro = intro;
        this.coverUrl = coverUrl;
        this.type = type;
    }
}

/**
 * 表示一个基本的章节。
 */
class BasicChapter {
    /**
     *
     * @param {String} title 章节的标题。必填。
     * @param {String} path 章节的路径。必填。
     * @param {Number} index 章节的索引。必填。
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({title, path, index} = {}) {
        if (typeof title !== 'string') throw new Error('BasicChapter: The "title" field must be a string and is required.');
        if (typeof path !== 'string') throw new Error('BasicChapter: The "path" field must be a string and is required.');
        if (typeof index !== 'number') throw new Error('BasicChapter: The "index" field must be a number and is required.');

        this.title = title;
        this.path = path;
        this.index = index;
    }
}

/**
 * 表示搜索书籍的结果。
 */
class SearchBookResult {
    /**
     *
     * @param {Number} pageNum 当前页码。必填。
     * @param {Number} pages 总页数。必填。
     * @param {String} keyword 搜索关键词。必填。
     * @param {BasicBook[]} bookList 书籍列表。必填。
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({pageNum, pages, keyword, bookList} = {}) {
        if (typeof pageNum !== 'number') throw new Error('SearchBookResult: The "pageNum" field must be a number and is required.');
        if (typeof pages !== 'number') throw new Error('SearchBookResult: The "pages" field must be a number and is required.');
        if (typeof keyword !== 'string') throw new Error('SearchBookResult: The "keyword" field must be a string and is required.');
        if (!Array.isArray(bookList)) throw new Error('SearchBookResult: The "bookList" field must be an array of BasicBook and is required.');

        this.pageNum = pageNum;
        this.pages = pages;
        this.keyword = keyword;
        this.bookList = bookList;
        this.size = bookList?.length ?? 0;
    }
}

class BookSource {
    /**
     *
     * @param {String} subscriptionId 订阅id。必填。
     * @param {String} id 书源id。必填。
     * @param {String} name 书源名字。必填。
     * @param {Boolean} active 是否可用。必填。
     * @param {String} portalUrl 门户网站。必填。
     * @param {String} searchBaseUrl 搜索基础url。必填。
     * @param {String} bookBaseUrl 书籍基础url。必填。
     * @param {String|null} description 来源描述。
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({subscriptionId, id, name, active, portalUrl, searchBaseUrl, bookBaseUrl, description = null} = {}) {
        if (typeof subscriptionId !== 'string') throw new Error('BookSource: The "subscriptionId" field must be a string and is required.');
        if (typeof id !== 'string') throw new Error('BookSource: The "id" field must be a string and is required.');
        if (typeof name !== 'string') throw new Error('BookSource: The "name" field must be a string and is required.');
        if (typeof active !== 'boolean') throw new Error('BookSource: The "active" field must be a boolean and is required.');
        if (typeof portalUrl !== 'string') throw new Error('BookSource: The "portalUrl" field must be a string and is required.');
        if (typeof searchBaseUrl !== 'string') throw new Error('BookSource: The "searchBaseUrl" field must be a string and is required.');
        if (typeof bookBaseUrl !== 'string') throw new Error('BookSource: The "bookBaseUrl" field must be a string and is required.');
        if (description && typeof description !== 'string') throw new Error('BookSource: The "description" field must be a string.');

        this.subscriptionId = subscriptionId;
        this.id = id;
        this.name = name;
        this.active = active;
        this.portalUrl = portalUrl;
        this.searchBaseUrl = searchBaseUrl;
        this.bookBaseUrl = bookBaseUrl;
        this.description = description;
    }

    // 与订阅json中的结构保持一致，方便Ctrl + c、v
    static createTestBookSource({id, name, active, portalUrl, searchBaseUrl, bookBaseUrl}) {
        return new BookSource({
            subscriptionId: "test",
            id,
            name,
            active,
            portalUrl,
            searchBaseUrl,
            bookBaseUrl
        });
    }

}

export {
    BasicBook,
    Book,
    BasicChapter,
    SearchBookResult,
    BookSource,
}




